//exercise 1: generate and parse control.yaml
#include <boost/lexical_cast.hpp>
#include "OtherUtil.hpp"
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
using namespace btl::utility;

void makeYAML()
{
    YAML::Emitter out;
    std::map <std::string, int> mpOpr1;
    mpOpr1["load rgb images"] = 1;
    mpOpr1["load depth maps"] = 1;
	mpOpr1["load undistorted rgb images"] = 1;
    mpOpr1["load undistorted depth maps"] = 1;
	mpOpr1["undistort images"] = 1;
	mpOpr1["export undistorted rgb images"] = 1;
	mpOpr1["export undistorted depth images"] = 1;
    mpOpr1["calibrate extrinsics"] = 1;
	mpOpr1["export to xml"] = 1;
	mpOpr1["import from xml"] = 1;
	mpOpr1["calibrate ir camera offset"] = 1;
	mpOpr1["calibrate depth"] = 1;

	out << YAML::BeginSeq;
    out << mpOpr1;
    out << YAML::EndSeq;

	map <string, vector< int > > mpCornerCounts;
	vector< int > vnCornerCounts;
	vnCornerCounts.push_back( 8 );
	vnCornerCounts.push_back( 6 );
	mpCornerCounts["No. of Corners X Y"] = vnCornerCounts;

	out << YAML::BeginSeq;
	out << YAML::Flow;
 	out << mpCornerCounts;
	out << YAML::EndSeq;

	map <string, vector< float > > mpUnitLength;
	vector< float > vfUnitLength;
	vfUnitLength.push_back( .03f );
	vfUnitLength.push_back( .03f );
	mpUnitLength["Unit length in X Y"] = vfUnitLength;

	out << YAML::BeginSeq;
	out << YAML::Flow;
 	out << mpUnitLength;
	out << YAML::EndSeq;



	std::map <std::string, string> mpProperties;
    mpProperties["image director"] = "Img/";

	out << YAML::BeginSeq;
 	out << mpProperties;
	out << YAML::EndSeq;

	std::vector<string> vRGBNames, vDepthNames, vUndistRGB, vUndistDepth;
	for(int i = 1; i < 22; i++)
	{
		string strNum = boost::lexical_cast<string> ( i );
        string strRGBFileName = "rgb" + strNum + ".bmp";
		string strDepthFileName = "depth" + strNum + ".bmp";
		string strUndistortedRGB = "rgbUndistorted" + strNum + ".bmp";
		string strUnistortedDepth = "depthUndistorted" + strNum + ".bmp";

    	vRGBNames.push_back( strRGBFileName );
		vDepthNames.push_back( strDepthFileName );
		vUndistRGB.push_back( strUndistortedRGB );
		vUndistDepth.push_back( strUnistortedDepth );
	}

	out << YAML::BeginSeq;
	out << YAML::Flow;
 	out << vRGBNames;
	out << YAML::EndSeq;

	out << YAML::BeginSeq;
	out << YAML::Flow;
 	out << vDepthNames;
	out << YAML::EndSeq;

	out << YAML::BeginSeq;
	out << YAML::Flow;
 	out << vUndistRGB;
	out << YAML::EndSeq;

	out << YAML::BeginSeq;
	out << YAML::Flow;
 	out << vUndistDepth;
	out << YAML::EndSeq;

    ofstream oFile ( "control.yaml" ); 
    oFile << out.c_str();
}

void parseYAML()
{
    ifstream iFile ( "control.yaml" );
    YAML::Parser parser ( iFile );
    YAML::Node doc;
    parser.GetNextDocument ( doc );
	std::map <std::string, int> mpOpr1;
    for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> mpOpr1;
	}
	PRINT( mpOpr1 );
	// properties
	std::map <std::string, vector< int > > mpCornerCounts;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> mpCornerCounts;

	}
	PRINT( mpCornerCounts );

	std::map <std::string, vector< float > > mpUnitLength;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> mpUnitLength;
	}
	PRINT( mpUnitLength );


	std::map <std::string, string> mpProperties;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> mpProperties;
	}
	PRINT( mpProperties );

	vector<string> vRGBNames;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> vRGBNames;
	}
	PRINT( vRGBNames );
	
	vector<string> vDepthNames;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> vDepthNames;
	}
	PRINT( vDepthNames );

	vector<string> vUndistRGB;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> vUndistRGB;
	}
	PRINT( vUndistRGB );

	vector<string> vUndistDepth;
 	parser.GetNextDocument ( doc );
	for ( unsigned i = 0; i < doc.size(); i++ )
    {
		doc[i] >> vUndistDepth;
	}
	PRINT( vUndistDepth );

	return;
}

int main()
{
    makeYAML();
    parseYAML();
    return 0;
}

//tutorial 5:  a complete example of how to parse a complex YAML file
//http://code.google.com/p/yaml-cpp/wiki/HowToParseADocument
/*
#include "yaml-cpp/yaml.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>

// our data types
struct Vec3 {
   float x, y, z;
};

struct Power {
   std::string name;
   int damage;
};

struct Monster {
   std::string name;
   Vec3 position;
   std::vector <Power> powers;
};

// now the extraction operators for these types
void operator >> (const YAML::Node& node, Vec3& v) {
   node[0] >> v.x;
   node[1] >> v.y;
   node[2] >> v.z;
}

void operator >> (const YAML::Node& node, Power& power) {
   node["name"] >> power.name;
   node["damage"] >> power.damage;
}

void operator >> (const YAML::Node& node, Monster& monster) {
   node["name"] >> monster.name;
   node["position"] >> monster.position;
   const YAML::Node& powers = node["powers"];
   for(unsigned i=0;i<powers.size();i++) {
      Power power;
      powers[i] >> power;
      monster.powers.push_back(power);
   }
}

int main()
{
   std::ifstream fin("monster.yaml");
   YAML::Parser parser(fin);
   YAML::Node doc;
   parser.GetNextDocument(doc);
   for(unsigned i=0;i<doc.size();i++) {
      Monster monster;
      doc[i] >> monster;
      std::cout << monster.name << "\n";
   }

   return 0;
}
*/
//tutorial 4: STL Containers, and Other Overloads
/*
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <vector>
#include <map>
using namespace std;

int main()
{
    YAML::Emitter out;
    std::vector <int> squares;
    squares.push_back ( 1 );
    squares.push_back ( 4 );
    squares.push_back ( 9 );
    squares.push_back ( 16 );

    std::map <std::string, int> ages;
    ages["Daniel"] = 26;
    ages["Jesse"] = 24;

    out << YAML::BeginSeq;
    out << YAML::Flow << squares;
    out << ages;
    out << YAML::EndSeq;
    std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"

	return 0;
}
*/
//tutorial 3: Using Manipulators
//http://code.google.com/p/yaml-cpp/wiki/HowToEmitYAML
/*
#include <yaml-cpp/yaml.h>
#include <iostream>
using namespace std;

int main()
{
    YAML::Emitter out;
    out << YAML::Literal << "A\n B\n  C";

    out << YAML::Flow;
    out << YAML::BeginSeq << 2 << 3 << 5 << 7 << 11 << YAML::EndSeq;
    //comments
    out << YAML::BeginMap;
    out << YAML::Key << "method";
    out << YAML::Value << "least squares";
    out << YAML::Comment ( "should we change this method?" );
    out << YAML::EndMap;
    //aliases/anchors
    out << YAML::BeginSeq;
    out << YAML::Anchor ( "fred" );
    out << YAML::BeginMap;
    out << YAML::Key << "name" << YAML::Value << "Fred";
    out << YAML::Key << "age" << YAML::Value << "42";
    out << YAML::EndMap;
    out << YAML::Alias ( "fred" );
    out << YAML::EndSeq;

    std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
    return 0;
}
*/
//tutorial 2: Simple Lists and Maps
//http://code.google.com/p/yaml-cpp/wiki/HowToEmitYAML
/*
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
    ofstream oFile ( "test.yaml" ); //
    YAML::Emitter out;
    // list
    out << YAML::BeginSeq;
    out << "eggs";
    out << "bread";
    out << "milk";
    out << YAML::EndSeq;
    // map
    out << YAML::BeginMap;
    out << YAML::Key << "name";
    out << YAML::Value << "Ryan Braun";
    out << YAML::Key << "position";
    out << YAML::Value << "LF";
    out << YAML::EndMap;
    // These elements can, of course, be nested:
    out << YAML::BeginMap;
    out << YAML::Key << "name";
    out << YAML::Value << "Barack Obama";
    out << YAML::Key << "children";
    out << YAML::Value << YAML::BeginSeq << "Sasha" << "Malia" << YAML::EndSeq;
    out << YAML::EndMap;

    oFile << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
    return 0;
}
*/
//tutorial 1: Basic Emitting
//http://code.google.com/p/yaml-cpp/wiki/HowToEmitYAML
/*
#include <yaml-cpp/yaml.h>
#include <iostream>

int main()
{
   YAML::Emitter out;
   out << "Hello, World!";

   std::cout << "Here's the output YAML:\n" << out.c_str(); // prints "Hello, World!"
   return 0;
}
*/
